<?php
/**
 * 21天减重测评算法
 * Created by PhpStorm.
 * User: liao
 * Date: 2016/12/12
 * Time: 16:41
 */

namespace App\Services\Algo;

use App\Interf\Calculable;
use TestingItemService;
use App\Models\LogHelper;

class DWeightNoqrCodeAlgo extends BaseTestingAlgo implements Calculable
{
    public $allAnswers ;
    private $typeFourExpress ;
    public function __construct($tid, $answerStr, $typeFourExpress = null)
    {
        parent::__construct($tid, $answerStr);
        $this->typeFourExpress = $typeFourExpress;
        $this->allAnswers = $this->convertAllAnswers();
    }

    public function calculate()
    {
        return $this->entrance($this->tid, $this->answers);

    }

    /**
     * 将拼装后的答案转换成字符串
     * @return string
     */
    public function resultToStr(){
        return $this->arrToStr($this->answers);
    }


    public function getAllAnswer(){
        return $this->answers;
    }

    /**
     * @param $tid
     * @param $answers
     * @return float|null
     */
    protected function entrance($tid,$answers){
        $totalScore =18;
//        foreach ($answers as $answer){
//            $totalScore = $totalScore + $answer['weight'];
//        }
        return $totalScore;
    }


    protected function convertAllAnswers(){
        LogHelper::log('before calculate BMI=============>');
        LogHelper::log($this->answers);
        $BMIData = [];
        //先计算21题BMI

        LogHelper::log('this->typeFourExpress=============>');
        LogHelper::log($this->typeFourExpress);
        if($this->typeFourExpress){
            foreach ($this->typeFourExpress as $d){
                if($d['index'] == 21){
                    array_push($BMIData,$d);
                    break;
                }
            }

            $result = $this->fourTypeArray($BMIData,$this->answers);
            foreach($result as $v){
                array_push($this->answers,$v);
            }
        }
        LogHelper::log('after calculate BMI=============>');
        LogHelper::log($this->answers);
        $types = 6;
        $dymTypeData = TestingItemService::getItemsByQuestionType($this->tid,$types,'_SIX');
        if(count($dymTypeData)>0){
            foreach ($dymTypeData as $data){
                $expressStr = $data['expression'];
                $weight = $this->getSingleItemWeight($expressStr);
                $obj['index'] = $data['index'];
                $obj['answer'] = '';
                $obj['weight'] = $weight;
                array_push($this->answers,$obj);
            }
        }
        LogHelper::log('after CALCULATE TYPE SIX=============>');
        LogHelper::log($this->answers);
        //先合并所有的answer
//        array_merge($this->allAnswers,$this->answers);
        if($this->typeFourExpress){
            $fourTypeResult = $this->fourTypeArray($this->typeFourExpress,$this->answers);
            foreach($fourTypeResult as $v){
                array_push($this->answers,$v);
            }
        }
        LogHelper::log('after CALCULATE TYPE FOUR=============>');
        LogHelper::log($this->answers);
    }


    /**
     *  0<=$4&&$4<80:$4##0
    80<=$4&&$4<85:$4##2
    85<=$4&&$4<300:$4##3
     **/
    protected function convertExpression($expressionStr){
        $arr = [];
        $expressions = explode("|||",$expressionStr);
        if(count($expressions)>0){
            foreach ($expressions as $e){
                $data = explode('##',$e);
                $relateExp = $data[0];
                // 解析这种形式的表达式0<=$4&&$4<80:$4
                $condArr = explode(':',$relateExp);
                //如果不存在则构造一个
                $condition = $this->compactConditionStr($condArr[0]);
                $obj['condition'] = $condition;
                //拆分条件表达式中的所以和操作符号($和@)
                if($operateObj = $this->compactOperateStr($condArr[1])){
                    foreach ($operateObj as $key => $val){
                        $obj[$key] = $val;
                    }
                }else{
                    $obj['index'] = -1;
                    $obj['operate'] = '';
                }

                $obj['weight'] = $data[1];
                array_push($arr,$obj);
            }
        }
        return $arr;
    }


    /**
     * 获取单个type为6的类型的权重
     */
    protected function getSingleItemWeight($expressStr){
        $expressionList = $this->convertExpression($expressStr);
        $weight = 0;
        foreach ($expressionList as $exp){
            $answerObj = $this->getAnswerObjByIndex($exp['index'],$this->answers);
            $replaceStr = '';
            switch ($exp['operate']){
                case '@':
                    $replaceStr = $answerObj['weight'];
                    break;
                case '$':
                    $replaceStr = $answerObj['answer'];
                    break;
            }
            $search = $exp['operate'].$exp['index'];
            //首先替换表达式  $val=0<@23&&@23<4?1:0 中的@23，
            //同时下面的$val变量一定要与表达式中的$val保持一致，否则$val条件判断值取不到结果。
            $val = str_replace($search,$replaceStr,$exp['condition']);
            //通过php的eval函数计算php的表达式
            eval($val);
            if($val){
                //如果条件表达式条件成立则去权重。
                $weight = $exp['weight'];
                break;
            }
        }
        return $weight;
    }

    /**
     * 组装条件判断表达是表达式 形如《10<@23<=20这种
     * @param string $operateStr
     * @return array
     */
    protected function compactConditionStr($condition){
        //如果不存在则构建一个假的条件表达式
        $condition = $condition ? $condition : '1==0';
        //注意此处是php中的表达式，一定要带上分号，否则会出错。
        $condition = '$val='.$condition.'?1:0;';
        return $condition;
    }

    /**
     * 拆分操作表达式 形如@23或者$23这种
     * @param string $operateStr
     * @return array
     */
    protected function compactOperateStr($operateStr){
        $obj = [];
        $operateArr = ['@','$'];
        $firstLetter = substr($operateStr,0,1);
        if(in_array($firstLetter,$operateArr)){
            $obj['operate'] = $firstLetter ;
            $obj['index'] = (int)substr($operateStr,1);
        }
        return $obj;
    }






}